/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package types;

import java.io.BufferedReader;
import java.io.DataInputStream;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author ali
 *
 * verwaltet das sudoku brett.
 * bietet setter und getter methoden an
 * wichtig: die array hat eine länge von 10,
 * die index 0 wird nicht benutz
 * also nur die felder 1-9 werden belegt.
 *
 * in initialzustand zeigen curRow und curCol auf das erste leere feld.
 *
 *

 */
public class SudokuBoard {

    private int[][] board = new int[10][10];

    public int[][] getBoard() {
        return board;
    }

    private int curRow = 1;
    private int curCol = 0;
    boolean solved = false;

    /**
     * jumps to the next empty field
     */
    public void jumpToNextEmptyField(){

        curCol++;
        for (int i = curRow; i < 10; i++)
        {
            for (int j=curCol;j<10;j++)
            {
                if (board[i][j] == 0)
                {
                    curRow = i;
                    curCol = j;
                    return;
                }
            }
            curCol=1;
        }

        //end of the board -> jump to (1,1) if the game would have not solved yet.
        if (this.isSolved() != true)
        {
            curCol=0;
            curRow=1;
            jumpToNextEmptyField();
        }
    }

    public int getCurRow()
    {
        return this.curRow;
    }

    public int getCurcol()
    {
        return this.curCol;
    }

    public SudokuBoard(String pathOfFile) throws FileNotFoundException {
        try {
            int r = 1;

            FileInputStream fstream = new FileInputStream(pathOfFile);
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String strLine;

            while ((strLine = br.readLine()) != null) {

                String[] digits = strLine.split("\t");

                for (int c = 1; c < 10; c++) {
                    this.board[r][c] = Integer.valueOf(digits[c - 1]).intValue();

                }

                r++;
            }

            //Close the input stream
            in.close();

            this.jumpToNextEmptyField();
        } catch (Exception e) {//Catch exception if any
            System.err.println("Error: " + e.getMessage());
        }

    }

    public int getDigit(int row, int col) throws Exception {
        if (row<1 || row >9 || col <1 || col >9)
            throw new Exception ("Invalid row|col number");
        return board[row][col];
    }

    public Collection getDisigtsSameRow(int row) throws Exception {
        
        if (row<1 || row >9)
            throw new Exception ("Invalid row number");

        Collection a = new ArrayList();
        for (int i = 1; i<10; i++)
            a.add(board[row][i]);
        return a;
    }

    public Collection getDigistsSameCol(int col) throws Exception {

        if (col<1 || col >9)
            throw new Exception ("Invalid row number");

        Collection a = new ArrayList();
        for (int i = 1; i < 10; i++) {
            a.add (board[i][col]);
        }
        return a;
    }

    public Collection getDigitsSameQuadrat(int row, int col) throws Exception {

        if (row<1 || row >9 || col <1 || col >9)
            throw new Exception ("Invalid row|col number");

        int quadrat = this.calculateQuadratNumber(row, col);

        Collection digits = new ArrayList();

        if (quadrat == 1) {
            for (int i = 1; i < 4; i++) {
                for (int j = 1; j < 4; j++) {
                    digits.add(board[i][j]);
                }
            }
            return digits;
        } else if (quadrat == 2) {
            for (int i = 1; i < 4; i++) {
                for (int j = 4; j < 7; j++) {
                    digits.add(board[i][j]);
                }
            }
            return digits;
        } else if (quadrat == 3) {
            for (int i = 1; i < 4; i++) {
                for (int j = 7; j < 10; j++) {
                    digits.add(board[i][j]);
                }
            }
            return digits;
        } else if (quadrat == 4) {
            for (int i = 4; i < 7; i++) {
                for (int j = 1; j < 4; j++) {
                    digits.add(board[i][j]);
                }
            }
            return digits;
        } else if (quadrat == 5) {
            for (int i = 4; i < 7; i++) {
                for (int j = 4; j < 7; j++) {
                    digits.add(board[i][j]);
                }
            }
            return digits;
        } else if (quadrat == 6) {
            for (int i = 4; i < 7; i++) {
                for (int j = 7; j < 10; j++) {
                    digits.add(board[i][j]);
                }
            }
            return digits;
        } else if (quadrat == 7) {
            for (int i = 7; i < 10; i++) {
                for (int j = 1; j < 4; j++) {
                    digits.add(board[i][j]);
                }
            }
            return digits;
        } else if (quadrat == 8) {
            for (int i = 7; i < 10; i++) {
                for (int j = 4; j < 7; j++) {
                    digits.add(board[i][j]);
                }
            }
            return digits;
        } else if (quadrat == 9) {
            for (int i = 7; i < 10; i++) {
                for (int j = 7; j < 10; j++) {
                    digits.add(board[i][j]);
                }
            }
            return digits;
        }
        throw new Exception("invalid field!");
    }

    /**
     * caqlculates the quadrat a field belongs to
     * @param row
     * @param col
     * @return
     * * sudokuboard:
     *  +++++++++++++
     *  + 1 + 2 + 3 +
     *  +++++++++++++
     *  + 4 + 5 + 6 +
     *  +++++++++++++
     *  + 7 + 8 + 9 +
     *  +++++++++++++
     */
    public int calculateQuadratNumber(int row, int col) throws Exception {
        if (row < 4) {
            if (col < 4) {
                return 1;
            } else if (col < 7) {
                return 2;
            } else if (col < 10) {
                return 3;
            }
        } else if (row < 7) {
            if (col < 4) {
                return 4;
            } else if (col < 7) {
                return 5;
            } else if (col < 10) {
                return 6;
            }
        } else if (row < 10) {
            if (col < 4) {
                return 7;
            } else if (col < 7) {
                return 8;
            } else if (col < 10) {
                return 9;
            }
        }

        throw new Exception("invalid field!");
    }

    private boolean isSolved() {
        for (int i = 1; i<10;i++)
            for (int j=1; j<10;j++)
            {
                if (this.board[i][j] == 0)
                    return false;
            }
        return true;
    }
}
